/******************************************************************************
*
* This file is part of FreeTrack (http://code.google.com/p/qtfreetrack).
* BY Willy Gardiol (willy@gardiol.org)
*
* FreeTrack is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeTrack is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar.  If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
#include "layermapcalibrate.h"
#include "layermap.h"
#include "ftpushbutton.h"

#define MARKER_OFFSET_X -15
#define MARKER_OFFSET_Y -47

LayerMapCalibrate::LayerMapCalibrate(LayerMap* m) :
    FreeTrackWidget(0)
{
    map = m;
    QList<QPoint> xy;
    map->getPointsXY( xy );
    point1 = xy.at(0);
    point2 = xy.at(1);
    point3 = xy.at(2);


    zoom_in = new FTPushButton( QIcon(":/icons/zoom_in.png"), ICON_SIZE );
    connect( zoom_in, SIGNAL(clicked()), this, SLOT(zoomIn()));

    zoom_out = new FTPushButton(QIcon(":/icons/zoom_out.png"), ICON_SIZE);
    connect( zoom_out, SIGNAL(clicked()), this, SLOT(zoomOut()));

    point1_button = new FTPushButton( QIcon(":/icons/marker1.png"), ICON_SIZE );
    connect(point1_button, SIGNAL(clicked()), this, SLOT(setPoint1()));

    point2_button = new FTPushButton( QIcon(":/icons/marker2.png"), ICON_SIZE);
    connect(point2_button, SIGNAL(clicked()), this, SLOT(setPoint2()));

    point3_button = new FTPushButton( QIcon(":/icons/marker3.png"), ICON_SIZE );
    connect(point3_button, SIGNAL(clicked()), this, SLOT(setPoint3()));

    point1_icon = QPixmap( ":/icons/marker1.png" );
    point2_icon = QPixmap( ":/icons/marker2.png" );
    point3_icon = QPixmap( ":/icons/marker3.png" );

    QRect map_rect = map->getRect();
    center = QPoint( map_rect.width()/2, map_rect.height()/2 );
    zoom_factor = 1.0;
}

LayerMapCalibrate::~LayerMapCalibrate()
{
}

void LayerMapCalibrate::zoomIn()
{
    if ( zoom_factor < 4.0)
        zoom_factor *= 2.0;
    update();
}

void LayerMapCalibrate::zoomOut()
{
    if ( zoom_factor > 0.01)
        zoom_factor /= 2.0;
    update();
}

void LayerMapCalibrate::setPoint1()
{
    if ( QMessageBox::question( this,
                                tr("Set point 1"),
                                tr("Move point 1 here?"),
                                QMessageBox::Yes|QMessageBox::No,
                                QMessageBox::NoButton ) != QMessageBox::Yes )
        return;

    point1 = center;
    emit pointChanged( 1, point1 );
}

void LayerMapCalibrate::setPoint2()
{
    if ( QMessageBox::question( this,
                                tr("Set point 2"),
                                tr("Move point 2 here?"),
                                QMessageBox::Yes|QMessageBox::No,
                                QMessageBox::NoButton ) != QMessageBox::Yes )
        return;

    point2 = center;
    emit pointChanged( 2, point2 );
}

void LayerMapCalibrate::setPoint3()
{
    if ( QMessageBox::question( this,
                                tr("Set point 3"),
                                tr("Move point 3 here?"),
                                QMessageBox::Yes|QMessageBox::No,
                                QMessageBox::NoButton ) != QMessageBox::Yes )
        return;

    point3 = center;
    emit pointChanged( 3, point3 );
}

void LayerMapCalibrate::mousePressEvent ( QMouseEvent * event )
{
    mouse_start = event->pos();
}

void LayerMapCalibrate::mouseReleaseEvent ( QMouseEvent * event )
{
    center += QPoint( (mouse_start.x()-event->pos().x())/zoom_factor,
                      (mouse_start.y()-event->pos().y())/zoom_factor );
    update();
}

void LayerMapCalibrate::mouseMoveEvent ( QMouseEvent * event )
{
    mouseReleaseEvent(event);
    mouse_start = event->pos();
}

void LayerMapCalibrate::updatePoint(int p, QPoint pt)
{
    if ( p == 1 )
        point1 = pt;
    else if ( p == 2 )
        point2 = pt;
    else if ( p == 3 )
        point3 = pt;
    update();
}

void LayerMapCalibrate::paintEvent(QPaintEvent *event)
{
    // this is the ORIGINAL size.
    int original_width = width(),
        original_height = height();

    // This is the new zoomed size (this is how much you can see on the screen)
    int new_width = original_width / zoom_factor,
        new_height = original_height / zoom_factor;

    // This is how much every item will be translated on the screen (which also represent the top-left corner of the screen
    // after the translation), so we need to use the scaled sizes here!
    QPoint translation_offset( center.x() - new_width/2,
                               center.y() - new_height/2 );

    // This is the rectangle we must "cut" on the source bitmap.
    // This rectangle must be expressed in IMAGE coordinates with 0,0 being the image top-left corner, which we
    // place at the 0,0 corner of our reference system. So, the "crop" rectangle top-left will be the
    // translation_offset, and the size will be the "scaled" size.
    QRect visible_area( translation_offset, QSize( new_width, new_height ));

    QPainter painter(this);

    painter.save();
    // Apply the zooming factor
    painter.scale( zoom_factor, zoom_factor );
    // Translate: translation_offset is how much the items get moved away from their original position to
    // end up in the screen. So, for example, translation_offset becomes (0,0) on the screen!
    painter.translate( -translation_offset );

    // REMEMBER: FROM NOW ON, WE PAINT ALWAYS IN THE ITEMS ORIGINAL POSITIONS...
    // those positions will be translated _by the painter_ to show up on the screen properly.

    // Draw the cropped map
    map->paintUncalibrated( painter, QPoint(0,0), visible_area );
    // Draw each marker
    painter.drawPixmap( point1 + QPoint( MARKER_OFFSET_X, MARKER_OFFSET_Y), point1_icon );
    painter.drawPixmap( point2 + QPoint( MARKER_OFFSET_X, MARKER_OFFSET_Y), point2_icon );
    painter.drawPixmap( point3 + QPoint( MARKER_OFFSET_X, MARKER_OFFSET_Y), point3_icon );

    painter.restore();

    // Put the screen zero point back into mid-screen... (now, here its unscaled)
    painter.translate( original_width/2, original_height/2 );
    QPen pen = QPen( QColor(255,255,255) );
    pen.setWidth(9);
    // Draw the "aiming cross" (TODO: change with a bitmap?)
    painter.drawLine( -20, 0, -10, 0);
    painter.drawLine( 10, 0, 20, 0);
    painter.drawLine( 0, -20, 0, -10);
    painter.drawLine( 0, 10, 0, 20);
    pen.setWidth(1);
    painter.drawLine( -10, 0, 10, 0);
    painter.drawLine( 0, -10, 0, 10);
}

QLayout* LayerMapCalibrate::createHorizontal()
{
    QHBoxLayout* grid = new QHBoxLayout();
    grid->addStretch();
    QVBoxLayout* bGrid = new QVBoxLayout();
    bGrid->addWidget( zoom_in );
    bGrid->addStretch();
    bGrid->addWidget( point1_button );
    bGrid->addStretch();
    bGrid->addWidget( point2_button );
    bGrid->addStretch();
    bGrid->addWidget( point3_button );
    bGrid->addStretch();
    bGrid->addWidget( zoom_out );
    bGrid->addStretch();

    grid->addLayout(bGrid);
    return grid;
}

QLayout* LayerMapCalibrate::createVertical()
{
    QVBoxLayout* grid = new QVBoxLayout();
    grid->addStretch();
    QHBoxLayout* bGrid = new QHBoxLayout();
    bGrid->addWidget( zoom_in );
    bGrid->addStretch();
    bGrid->addWidget( point1_button );
    bGrid->addStretch();
    bGrid->addWidget( point2_button );
    bGrid->addStretch();
    bGrid->addWidget( point3_button );
    bGrid->addStretch();
    bGrid->addWidget( zoom_out );
    bGrid->addStretch();

    grid->addLayout(bGrid);
    return grid;
}
